using System;

namespace System.IO
{
	/// <summary>
	/// A stream type that has two underlying streams - one for input, and a different one for output.
	/// Currently detected uses for this class == 0. ;-)
	/// </summary>
	public class SplitStream : System.IO.Stream
	{
		private const string ss_noseek = "The SplitStream does not support Seek operations!";

		#region Private Variables
		private System.IO.Stream _InputStream;
		private System.IO.Stream _OutputStream;
		#endregion

		#region Constructors
		private SplitStream()
		{
		}
		public SplitStream(System.IO.Stream inputStream, System.IO.Stream outputStream)
		{
			if(inputStream==null)
				throw new ArgumentNullException("inputStream");
			if(outputStream==null)
				throw new ArgumentNullException("outputStream");
			if(inputStream.CanRead==false)
				throw new ArgumentException("The SplitStream's 'inputStream' must be readable!");
			if(outputStream.CanWrite==false)
				throw new ArgumentException("The SplitStream's 'outputStream' must be writable!");
			if(inputStream==outputStream)
				throw new ArgumentException("The SplitStream's 'inputStream' and 'outputStream' need to be two different streams!!");

			this._InputStream = inputStream;
			this._OutputStream = outputStream;
		}
		#endregion

		#region Funtionality Detection
		public override bool CanRead
		{
			get
			{
				return true;
			}
		}

		public override bool CanSeek
		{
			get
			{
				return false;
			}
		}
		
		public override bool CanWrite
		{
			get
			{
				return true;
			}
		}

		#endregion

		#region Seeking
		public override long Length
		{
			get
			{
				throw new InvalidOperationException(SplitStream.ss_noseek);
			}
		}

		public override long Position
		{
			get
			{
				throw new InvalidOperationException(SplitStream.ss_noseek);
			}
			set
			{
				throw new InvalidOperationException(SplitStream.ss_noseek);
			}
		}

		public override void SetLength(long value)
		{
			throw new InvalidOperationException(SplitStream.ss_noseek);
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new InvalidOperationException(SplitStream.ss_noseek);
		}
		#endregion

		#region Maintenance
		public override void Flush()
		{
			this._InputStream.Flush();
			this._OutputStream.Flush();
		}

		public override void Close()
		{
			this._InputStream.Close();
			this._OutputStream.Close();
		}
		#endregion

		#region Reading
		public override int Read(byte[] buffer, int offset, int count)
		{
			return _InputStream.Read(buffer,offset,count);
		}
		public override int ReadByte()
		{
			return _InputStream.ReadByte();
		}
		#endregion

		#region Writing
		public override void Write(byte[] buffer, int offset, int count)
		{
			_OutputStream.Write(buffer,offset,count);
		}
		public override void WriteByte(byte value)
		{
			_OutputStream.WriteByte(value);
		}
		#endregion
	}
}
